package de.baumann.browser.utils.web3j;

import android.util.Log;

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthGasPrice;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Contract;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;

public class Erc20Util {

    private static Web3j getweb3j(String url) {
        return Web3j.build(new HttpService(url));
    }

    public static String transferERC20Token(
            String url,
            String from,
            String to,
            String value,
            String privateKey,
            String contractAddress) throws Exception {
        //加载转账所需的凭证，用私钥
        Log.d("222222", url+"=="+from+"=="+to+"=="+value+"+transferERC20Token: " + contractAddress);
        Credentials credentials = Credentials.create(privateKey);
        //获取nonce，交易笔数
        BigInteger nonce = getNonce(url, from);
        //get gasPrice
        BigInteger gasPrice = getGasPrice(url);
        BigInteger gasLimit = Contract.GAS_LIMIT;

        //创建RawTransaction交易对象
        Function function = new Function(
                "transfer",
                Arrays.asList(new Address(to), new Uint256(Convert.toWei(value, Convert.Unit.ETHER).toBigInteger())),
                Arrays.asList(new TypeReference<Type>() {
                }));

        String encodedFunction = FunctionEncoder.encode(function);

        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                gasPrice,
                gasLimit,
                contractAddress,
                encodedFunction);


        //签名Transaction，这里要对交易做签名
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signMessage);
        //发送交易
        EthSendTransaction ethSendTransaction = getweb3j(url).ethSendRawTransaction(hexValue).sendAsync().get();
        String hash = ethSendTransaction.getTransactionHash();
        Log.d("222222", "transferERC20Token: " + hash);
        return hash;
    }


    public static String transferERC20Token2(
            String url,
            String from,
            String value,
            String privateKey,
            String contractAddress) throws Exception {
        //加载转账所需的凭证，用私钥
        Credentials credentials = Credentials.create(privateKey);
        //获取nonce，交易笔数
        BigInteger nonce = getNonce(url, from);
        //get gasPrice
        BigInteger gasPrice = getGasPrice(url);
        BigInteger gasLimit = Contract.GAS_LIMIT;


        //创建RawTransaction交易对象
        Function function = new Function(
                "ownerDeposit",
                Arrays.asList(new Uint256(12)),
                Arrays.asList(new TypeReference<Type>() {
                }));

        String encodedFunction = FunctionEncoder.encode(function);
        BigDecimal weiValue = Convert.toWei(value, Convert.Unit.ETHER);
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                gasPrice,
                gasLimit,
                contractAddress,
                weiValue.toBigInteger(),
                encodedFunction);

        //签名Transaction，这里要对交易做签名
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signMessage);
        //发送交易
        EthSendTransaction ethSendTransaction = getweb3j(url).ethSendRawTransaction(hexValue).sendAsync().get();
        String hash = ethSendTransaction.getTransactionHash();
        Log.d("222222", "transferERC20Token: " + hash);
        return hash;
    }


    public static String transferERC20Token3(
            String url,
            String from,
            String smelterAddress,
            Long time,
            String privateKey,
            String contractAddress,
            String value) throws Exception {
        //加载转账所需的凭证，用私钥
        Credentials credentials = Credentials.create(privateKey);
        //获取nonce，交易笔数
        BigInteger nonce = getNonce(url, from);
        //get gasPrice
        BigInteger gasPrice = getGasPrice(url);
        BigInteger gasLimit = Contract.GAS_LIMIT;

        //创建RawTransaction交易对象
        Function function = new Function(
                "userDeposit",
                Arrays.asList(new Address(smelterAddress), new Uint256(time)),
                Arrays.asList(new TypeReference<Type>() {
                }));

        String encodedFunction = FunctionEncoder.encode(function);

        BigDecimal weiValue = Convert.toWei(value, Convert.Unit.ETHER);
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                gasPrice,
                gasLimit,
                contractAddress,
                weiValue.toBigInteger(),
                encodedFunction);

        //签名Transaction，这里要对交易做签名
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signMessage);
        //发送交易
        EthSendTransaction ethSendTransaction = getweb3j(url).ethSendRawTransaction(hexValue).sendAsync().get();
        String hash = ethSendTransaction.getTransactionHash();
        Log.d("222222", "transferERC20Token: " + hash);
        return hash;
    }

    private static BigInteger getNonce(String url, String from) throws ExecutionException, InterruptedException {
        EthGetTransactionCount transactionCount = getweb3j(url).ethGetTransactionCount(from, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = transactionCount.getTransactionCount();
        return nonce;
    }


    private static BigInteger getGasPrice(String url) {
        try {
            EthGasPrice price = getweb3j(url).ethGasPrice().sendAsync().get();
            BigInteger gasPrice = price.getGasPrice();
            return gasPrice;
        } catch (Exception e) {
            Log.e("gasPrice失败:{}", e.getMessage());
        }
        return null;
    }

    public static void endTime(String url, String contractAddress, String address) throws Exception {
        Function function = new Function(
                "ownerUserCounts",
                Arrays.asList(new Address("0xF2D792e3FBE48133377203735f81BD512Cc113AA")),
                Arrays.asList(new TypeReference<Uint256>() {
                }));
        String responseValue = TokenUtil.callSmartContractFunction(url, function, contractAddress, address);
        List<Type> response = FunctionReturnDecoder.decode(
                responseValue, function.getOutputParameters());
        BigDecimal decimal = Convert.fromWei(new BigDecimal(((Uint256) response.get(0)).getValue()), Convert.Unit.WEI);
    }

    public static BigDecimal userDepositsNum(String nodeUrl, String contractAddress, String smelterAddress, String userAddress) throws Exception {
        Function function = new Function(
                "userDeposits",
                Arrays.asList(new Address(smelterAddress), new Address(userAddress)),
                Arrays.asList(new TypeReference<Uint256>() {
                }));
        String responseValue = TokenUtil.callSmartContractFunction(nodeUrl, function, contractAddress, userAddress);
        List<Type> response = FunctionReturnDecoder.decode(
                responseValue, function.getOutputParameters());
        BigDecimal decimal = Convert.fromWei(new BigDecimal(((Uint256) response.get(0)).getValue()), Convert.Unit.ETHER);
        return decimal;
    }

    public static BigDecimal ownerUserCounts(String nodeUrl, String contractAddress, String smelterAddress) throws Exception {
        Function function = new Function(
                "ownerUserCounts",
                Arrays.asList(new Address(smelterAddress)),
                Arrays.asList(new TypeReference<Uint256>() {
                }));
        String responseValue = TokenUtil.callSmartContractFunction(nodeUrl, function, contractAddress, smelterAddress);
        List<Type> response = FunctionReturnDecoder.decode(
                responseValue, function.getOutputParameters());
        BigDecimal decimal = Convert.fromWei(new BigDecimal(((Uint256) response.get(0)).getValue()), Convert.Unit.WEI);
        Log.d("1111", "-------------" + decimal);
        return decimal;
    }

    public static String userWithdraw(String nodeUrl,
                                      String userAddress,
                                      String amount,
                                      String privateKey,
                                      String contractAddress) throws ExecutionException, InterruptedException {

        //获取nonce，交易笔数
        BigInteger nonce = getNonce(nodeUrl, userAddress);
        //get gasPrice
        BigInteger gasPrice = getGasPrice(nodeUrl);
        BigInteger gasLimit = Contract.GAS_LIMIT;
        //创建RawTransaction交易对象
        Function function = new Function(
                "userWithdraw",
                Arrays.asList(new Address(userAddress)),
                Arrays.asList(new TypeReference<Type>() {
                }));

        String encodedFunction = FunctionEncoder.encode(function);

//        BigDecimal weiValue =  Convert.toWei(value, Convert.Unit.ETHER);
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                gasPrice,
                gasLimit,
                contractAddress,
//                weiValue.toBigInteger(),
                encodedFunction);

        //加载转账所需的凭证，用私钥
        Credentials credentials = Credentials.create(privateKey);

        //签名Transaction，这里要对交易做签名
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signMessage);
        //发送交易
        EthSendTransaction ethSendTransaction = getweb3j(nodeUrl).ethSendRawTransaction(hexValue).sendAsync().get();
        String hash = ethSendTransaction.getTransactionHash();
        Log.d("1111", "------------" + hash);
        return hash;
    }

    public static String userWithdraw2(String nodeUrl,
                                      String userAddress,
                                      String amount,
                                      String privateKey,
                                      String contractAddress) throws ExecutionException, InterruptedException {
        //加载转账所需的凭证，用私钥
        Credentials credentials = Credentials.create(privateKey);
        //获取nonce，交易笔数
        BigInteger nonce = getNonce(nodeUrl, userAddress);
        //get gasPrice
        BigInteger gasPrice = getGasPrice(nodeUrl);
        BigInteger gasLimit = Contract.GAS_LIMIT;


        //创建RawTransaction交易对象
        Function function = new Function(
                "userWithdraw",
                Arrays.asList(),
                Arrays.asList(new TypeReference<Type>() {
                }));

        String encodedFunction = FunctionEncoder.encode(function);
//        BigDecimal weiValue = Convert.toWei(value, Convert.Unit.ETHER);
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                gasPrice,
                gasLimit,
                contractAddress,
//                weiValue.toBigInteger(),
                encodedFunction);

        //签名Transaction，这里要对交易做签名
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signMessage);
        //发送交易
        EthSendTransaction ethSendTransaction = getweb3j(nodeUrl).ethSendRawTransaction(hexValue).sendAsync().get();
        String hash = ethSendTransaction.getTransactionHash();
        Log.d("222222", "transferERC20Token: " + hash);
        return hash;
    }
    public static String ownerWithdraw(String nodeUrl,
                                      String userAddress,
                                      String privateKey,
                                      String contractAddress) throws ExecutionException, InterruptedException {

        //获取nonce，交易笔数
        BigInteger nonce = getNonce(nodeUrl, userAddress);
        //get gasPrice
        BigInteger gasPrice = getGasPrice(nodeUrl);
        BigInteger gasLimit = Contract.GAS_LIMIT;
        //创建RawTransaction交易对象
        Function function = new Function(
                "ownerWithdraw",
                Arrays.asList(),
                Arrays.asList(new TypeReference<Type>() {
                }));

        String encodedFunction = FunctionEncoder.encode(function);

        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                gasPrice,
                gasLimit,
                contractAddress,
                encodedFunction);

        //加载转账所需的凭证，用私钥
        Credentials credentials = Credentials.create(privateKey);

        //签名Transaction，这里要对交易做签名
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signMessage);
        //发送交易
        EthSendTransaction ethSendTransaction = getweb3j(nodeUrl).ethSendRawTransaction(hexValue).sendAsync().get();
        String hash = ethSendTransaction.getTransactionHash();
        Log.d("1111", "------------" + hash);
        return hash;
    }

}
